package com.example.easyexcel.aop.monitor;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

/**
 * 创建AOP切面
 */
@Aspect
@Component
@Slf4j
public class ExecutionTimeAspect {

    @Around("@annotation(executionTimeMonitor)")
    public Object monitorExecutionTime(ProceedingJoinPoint joinPoint,
                                       ExecutionTimeMonitor executionTimeMonitor) throws Throwable {
        // 直接获取方法名，避免 getMethod() 调用
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String monitorName = executionTimeMonitor.value().isEmpty() ?
                className + "." + methodName : executionTimeMonitor.value();

        StopWatch stopWatch = new StopWatch(monitorName);
        stopWatch.start();

        try {
            Object result = joinPoint.proceed();
            stopWatch.stop();

            logExecutionTime(joinPoint, executionTimeMonitor, stopWatch, null);
            return result;

        } catch (Exception e) {
            stopWatch.stop();
            logExecutionTime(joinPoint, executionTimeMonitor, stopWatch, e);
            throw e;
        }
    }

    private void logExecutionTime(ProceedingJoinPoint joinPoint,
                                  ExecutionTimeMonitor executionTimeMonitor,
                                  StopWatch stopWatch, Exception exception) {
        String taskName = stopWatch.getId();
        long totalTimeMillis = stopWatch.getTotalTimeMillis();

        if (exception != null) {
            log.error("{} 执行失败，已耗时: {} 毫秒", taskName, totalTimeMillis, exception);
        } else {
            log.info("{} 执行完成，耗时: {} 毫秒", taskName, totalTimeMillis);

            if (executionTimeMonitor.logParameters()) {
                log.debug("{} 方法参数: {}", taskName, getMethodParameters(joinPoint));
            }
        }
    }

    private String getMethodParameters(ProceedingJoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return "无参数";
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < args.length; i++) {
            if (args[i] != null) {
                sb.append("参数").append(i + 1).append(": ")
                        .append(args[i].getClass().getSimpleName()).append(", ");
            } else {
                sb.append("参数").append(i + 1).append(": null, ");
            }
        }
        return sb.toString();
    }
}